package cn.miao.hrm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.StrSplitter;
import cn.miao.constant.RedisConst;
import cn.miao.hrm.domain.CourseType;
import cn.miao.hrm.mapper.CourseTypeMapper;
import cn.miao.hrm.service.ICourseTypeService;
import cn.miao.hrm.vo.CrumbsVo;
import cn.miao.util.AjaxResult;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author MiaoDaWei
 * @since 2021-11-26
 */
@Service
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {

    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate<Object, Object> redisTemplate;

    @Override
    //CacheEvict删除redis中的key,在方法执行后返回的布尔值,如果为true那么就执行删除redis中的指定key
    @CacheEvict(cacheNames = RedisConst.KEY_COURSE_TYPE_PREFIX, key = RedisConst.KEY_COURSE_TYPE_TREE)
    public boolean insert(CourseType entity) {
        return super.insert(entity);
    }

    @Override
    @CacheEvict(cacheNames = RedisConst.KEY_COURSE_TYPE_PREFIX, key = RedisConst.KEY_COURSE_TYPE_TREE)
    public boolean deleteById(Serializable id) {
        return super.deleteById(id);
    }

    @Override
    @CacheEvict(cacheNames = RedisConst.KEY_COURSE_TYPE_PREFIX, key = RedisConst.KEY_COURSE_TYPE_TREE)
    public boolean updateById(CourseType entity) {
        return super.updateById(entity);
    }

    /**
     * 获取树数据
     *
     * @return {@link AjaxResult}
     */
    @Override
    //每次读取树形数据都是从redis缓存中获取,如果获取不到再从方法里的数据库中执行.执行完毕根据返回结果存入redis缓存中!
    @Cacheable(cacheNames = RedisConst.KEY_COURSE_TYPE_PREFIX,key = RedisConst.KEY_COURSE_TYPE_TREE)
    public List<CourseType> getTreeData() {
//        List<CourseType> courseTypeTree = (List<CourseType>) redisTemplate.opsForValue().get(RedisConst.KEY_COURSE_TYPE_TREE);
//        if (CollUtil.isNotEmpty(courseTypeTree)) {
//            return courseTypeTree;
//        }
//        //如果查询不到就从数据库获取
//        List<CourseType> courseTypes = this.getTreeDataFromDB();
//        //4.缓存课程分类到Redis
//        redisTemplate.opsForValue().set(RedisConst.KEY_COURSE_TYPE_TREE, courseTypes, 6L, TimeUnit.DAYS);
//        //5.返回结果
        return this.getTreeDataFromDB();
    }

    /**
     * 面包屑
     *
     * @param id id
     * @return {@link AjaxResult}
     */
    @Override
    public AjaxResult crumbs(Long id) {
        CourseType courseType = this.selectById(id);
        //获取它的上面所有级
        List<String> stringList = StrSplitter.split(courseType.getPath(), ".", true, true);
        //批量查询
        List<CourseType> types = this.selectBatchIds(stringList);
        //循环处理
        List<CrumbsVo> crumbsVoList = new ArrayList<>();
        for (CourseType type : types) {
            CrumbsVo crumbsVo = new CrumbsVo();
            crumbsVo.setOwnerCourseType(type);
            //将自己的pid去找相同的pid,这样做是认为跟自己也是一样的同级节点
            List<CourseType> list = this.selectList(new EntityWrapper<CourseType>().eq("pid", type.getPid()));
            //去除除了我自己的
            list=list.stream().filter(x -> !x.getId().equals(type.getId())).collect(Collectors.toList());
            crumbsVo.setOtherCourseTypes(list);
            //添加
            crumbsVoList.add(crumbsVo);
        }


        return AjaxResult.me().setResultObj(crumbsVoList);
    }


    /**
     * 获取树性数据
     *
     * @return {@link AjaxResult}
     */

    public List<CourseType> getTreeDataFromDB() {
        //获取全部分类
        List<CourseType> allTypes = selectList(null);
        Map<Long, CourseType> parentMap = allTypes.stream().collect(Collectors.toMap(CourseType::getId, courseType -> courseType));

//        System.out.println(allTypes.get(0) == parentMap.get(1037L)); 判断是否是同一个对象

        //返回分级分类
        List<CourseType> resultTypes = new ArrayList<>();

        //循环
        for (CourseType courseType : allTypes) {
            if (Objects.isNull(courseType.getPid()) || courseType.getPid().compareTo(0L) == 0) {
                //如果父节点是0或者null那么就认为这是一级菜单
                resultTypes.add(courseType);
            } else {
//                //遍历全部分类
//                for (CourseType type : allTypes) {
//                    //如果当前父级id等同于父级id
//                    if (courseType.getPid().compareTo(type.getId()) == 0) {
//                        type.getChildren().add(courseType);
//                        break;
//                    }
//                }
                //这里获取是父级的菜单
                CourseType parameType = new CourseType();
                parameType = parentMap.get(courseType.getPid());
                if (BeanUtil.isNotEmpty(parameType)) {
                    parameType.getChildren().add(courseType);
                }
            }
        }
        return resultTypes;
    }
}
